﻿// KittyFeral PVE - HB Routine for FeralDruid 5.4 - By Neyia
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Action = Styx.TreeSharp.Action;

namespace KittyFeral
{
    public partial class Main : CombatRoutine
    {
        #region catrotation
        Composite CatRotation()
        {
            return 
                new PrioritySelector(
                Cast(CAT_FORM, ret => Me.Shapeshift != ShapeshiftForm.Cat),

                HealthstoneCat(),

                new Decorator(ret => gotTarget && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget), new Action(delegate { Me.CurrentTarget.Face(); return RunStatus.Failure; })),
                Cast(CENARION_WARD, ret => SpellManager.HasSpell(CENARION_WARD) && !spellOnCooldown(CENARION_WARD) && Me.HealthPercent <= CRSettingsCat.myPrefs.CenarionWard),
                CastOnMe(REJUVENATION, ret => !buffExists(REJUVENATION, Me) && (!SpellManager.HasSpell(PREDATORY_SWIFTNESS) || Solo) && Me.HealthPercent <= CRSettingsCat.myPrefs.RejuvenationCombat),
                CastWildCharge(WILD_CHARGE, ret => AllowMovement 
                    && !spellOnCooldown(WILD_CHARGE) 
                    && CRSettingsCat.myPrefs.useWildCharge
                    && Me.CurrentTarget.InLineOfSight 
                    && CanCastWildCharge(8, 25)),

                new Decorator(ret => gotTarget && SpellManager.HasSpell(SWIPE) && addCount >= CRSettingsCat.myPrefs.StartAoe && !PauseAoe, CatAoe()),
                new Decorator(ret => gotTarget && addCount < CRSettingsCat.myPrefs.StartAoe || PauseAoe || !SpellManager.HasSpell(SWIPE),
                new PrioritySelector(
                    Cast(FAERIE_FIRE, ret => gotTarget
                        && SpellManager.HasSpell(FAERIE_FIRE)
                        && !SpellManager.HasSpell(FAERIE_SWARM)
                        && !spellOnCooldown(FAERIE_FIRE)
                        && (!debuffExists(WEAKENED_ARMOR, Me.CurrentTarget) || !debuffExists(FAERIE_FIRE, Me.CurrentTarget))
                        && Me.CurrentTarget.Distance <= 35),
                    Cast(FAERIE_SWARM, ret => gotTarget
                        && !SpellManager.HasSpell(FAERIE_SWARM)
                        && !spellOnCooldown(FAERIE_FIRE)
                        && (!debuffExists(WEAKENED_ARMOR, Me.CurrentTarget) || !debuffExists(FAERIE_SWARM, Me.CurrentTarget))
                        && Me.CurrentTarget.Distance <= 35),
                    Cast(THRASH, ret => gotTarget
                        && buffExists(CLEARCASTING, Me)
                        && !debuffExists(WEAKENED_BLOWS, Me.CurrentTarget)
                        && Me.CurrentTarget.Distance <= 4
                        && LastSpell != THRASH),
                    Cast(FEROCIOUS_BITE, ret => gotTarget && Me.CurrentTarget.HealthPercent < 25
                                    && debuffExists(RIP, Me.CurrentTarget)
                                    && Me.ComboPoints >= 5
                                    && Me.CurrentTarget.Distance <= 4),
                    Cast(FORCE_OF_NATURE, ret => gotTarget 
                        && CRSettingsCat.myPrefs.ForceOfNature 
                        && UseForceOfNaure
                        && Me.CurrentTarget.Distance <= 4),
                    Cast(RIP, ret => gotTarget && isBoss
                                    && (!debuffExists(RIP, Me.CurrentTarget) || (debuffExists(RIP, Me.CurrentTarget) && debuffTimeLeft(RIP, Me.CurrentTarget) <= 6000))
                                    && Me.ComboPoints >= 5
                                    && Me.CurrentTarget.Distance <= 4),
                    Cast(FEROCIOUS_BITE, ret => gotTarget && isBoss
                                    && (debuffExists(RIP, Me.CurrentTarget) || (debuffExists(RIP, Me.CurrentTarget) && debuffTimeLeft(RIP, Me.CurrentTarget) > 6000))
                                    && Me.ComboPoints >= 5
                                    && Me.CurrentTarget.Distance <= 4),
                    Cast(SAVAGE_ROAR, ret => gotTarget && !buffExists(SAVAGE_ROAR, Me)),
                    Cast(RAKE, ret => gotTarget && (!debuffExists(RAKE, Me.CurrentTarget)
                                    || (debuffExists(RAKE, Me.CurrentTarget) && debuffTimeLeft(RAKE, Me.CurrentTarget) <= 5000))
                                    && Me.CurrentTarget.Distance <= 4),
                    Cast(WAR_STOMP, ret => gotTarget 
                        && Me.Race == WoWRace.Tauren 
                        && !spellOnCooldown(WAR_STOMP) 
                        && Me.CurrentTarget.IsCasting 
                        && (Me.CanInterruptCurrentSpellCast || NeedInterrupt)
                        && CRSettingsCat.myPrefs.AutoInterrupt
                        && LastSpell != MIGHTY_BASH && LastSpell != SKULL_BASH && Me.CurrentTarget.Distance <= 4),
                
                    Cast(MIGHTY_BASH, ret => gotTarget && SpellManager.HasSpell(MIGHTY_BASH)
                                     && !spellOnCooldown(MIGHTY_BASH)
                                     && CRSettingsCat.myPrefs.AutoInterrupt
                                     && Me.CurrentTarget.IsCasting
                                     && (Me.CanInterruptCurrentSpellCast || NeedInterrupt)
                                     && Me.CurrentTarget.Distance <= 4),
                    Cast(SKULL_BASH, ret => gotTarget && SpellManager.HasSpell(SKULL_BASH)
                        && CRSettingsCat.myPrefs.AutoInterrupt
                                    && !spellOnCooldown(SKULL_BASH)
                                    && Me.CurrentTarget.IsCasting
                                    && (Me.CanInterruptCurrentSpellCast || NeedInterrupt)
                                    && Me.CurrentTarget.Distance <= 4),
                    Cast(TIGERS_FURY, ret => gotTarget && SpellManager.HasSpell(TIGERS_FURY)
                                    && Me.EnergyPercent < 25
                                    && !spellOnCooldown(TIGERS_FURY)),
                    Cast(HEALING_TOUCH, ret => SpellManager.HasSpell(HEALING_TOUCH)
                                    && buffExists(PREDATORY_SWIFTNESS, Me)
                                    && LastSpell != HEALING_TOUCH),
                    Cast(FEROCIOUS_BITE, ret => gotTarget && !isBoss
                                    && Me.ComboPoints >= 3
                                    && Me.CurrentTarget.Distance <= 4),
                    Cast(BERSERK, ret => gotTarget && SpellManager.HasSpell(BERSERK)
                                    && isBoss
                                    && !spellOnCooldown(BERSERK)
                                    && Me.CurrentTarget.Distance <= 4),
                    Cast(INCARNATION, ret => gotTarget && SpellManager.HasSpell(INCARNATION)
                                    && isBoss
                                    && CRSettingsCat.myPrefs.useIncarnation
                                    && !spellOnCooldown(INCARNATION)
                                    && Me.CurrentTarget.Distance <= 4),
                    new Decorator(ret => gotTarget && Me.Combat && CRSettingsCat.myPrefs.useVirmenPotions && isBoss && Me.CurrentTarget.Distance <= 4 && !Me.CurrentTarget.Name.Contains("Dummy"), new Action(ret => { VirmenPotion(); return RunStatus.Failure; })),
                    
                    new Decorator(ret => gotTarget && Me.Combat && isBoss && Me.CurrentTarget.Distance <= 4, new Action(ret => { UseEngiGloves(); return RunStatus.Failure; })),
                    Cast(BERSERKING, ret => gotTarget && SpellManager.HasSpell(BERSERKING)
                                    && CRSettingsCat.myPrefs.useBerserking
                                    && !spellOnCooldown(BERSERKING)
                                    && NotHaveHasteBuffs()
                                    && Me.CurrentTarget.Distance <= 4),

                    Trinket1Cat(),
                    Trinket2Cat(),

                    Cast(LIFEBLOOD, ret => gotTarget 
                        && isBoss 
                        && NotHaveHasteBuffs() 
                        && !spellOnCooldown(LIFEBLOOD)
                        && Me.CurrentTarget.Distance <= 4),
                    Cast(RAVAGE, ret => gotTarget 
                        && SpellManager.HasSpell(RAVAGE)
                        && Me.CurrentTarget.Distance <= 4),
                    Cast(RAVAGE, ret => gotTarget 
                        && SpellManager.HasSpell(RAVAGE)
                        && buffExists(INCARNATION, Me)
                        && Me.CurrentTarget.Distance <= 4),
                    Cast(SHRED, ret => gotTarget 
                        && debuffExists(RAKE, Me.CurrentTarget) 
                        && Me.IsSafelyBehind(Me.CurrentTarget) 
                        && CRSettingsCat.myPrefs.useShred
                        && Me.CurrentTarget.Distance <= 4),
                    Cast(SHRED, ret => gotTarget && CRSettingsCat.myPrefs.HaveGlyphOfShred
                                    && CRSettingsCat.myPrefs.useShred
                                    && SpellManager.HasSpell(SHRED)
                                    && debuffExists(RAKE, Me.CurrentTarget)
                                    && (buffExists(BERSERK, Me) || buffExists(TIGERS_FURY, Me))
                                    && Me.CurrentTarget.Distance <= 4),
                    Cast(MANGLE, ret => gotTarget && Me.CurrentTarget.Distance <= 4)

                )));
        }
        #endregion

        #region catAoe
        Composite CatAoe()
        {
            return new PrioritySelector(
                Cast(CAT_FORM, ret => Me.Shapeshift != ShapeshiftForm.Cat),
                new Decorator(ret => gotTarget && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget), new Action(delegate { Me.CurrentTarget.Face(); return RunStatus.Failure; })),
                Cast(SAVAGE_ROAR, ret => gotTarget && !buffExists(SAVAGE_ROAR, Me)),
                Cast(TIGERS_FURY, ret => gotTarget && Me.EnergyPercent < 25 && !spellOnCooldown(TIGERS_FURY) && LastSpell != TIGERS_FURY),
                Cast(HEALING_TOUCH, ret => gotTarget && buffExists(PREDATORY_SWIFTNESS, Me) && LastSpell != HEALING_TOUCH),

                Cast(WAR_STOMP, ret => gotTarget
                        && Me.Race == WoWRace.Tauren
                        && !spellOnCooldown(WAR_STOMP)
                        && Me.CurrentTarget.IsCasting
                        && (Me.CanInterruptCurrentSpellCast || NeedInterrupt)
                        && CRSettingsCat.myPrefs.AutoInterrupt
                        && LastSpell != MIGHTY_BASH && LastSpell != SKULL_BASH && Me.CurrentTarget.Distance <= 4),

                    Cast(MIGHTY_BASH, ret => gotTarget && SpellManager.HasSpell(MIGHTY_BASH)
                                     && !spellOnCooldown(MIGHTY_BASH)
                                     && CRSettingsCat.myPrefs.AutoInterrupt
                                     && Me.CurrentTarget.IsCasting
                                     && (Me.CanInterruptCurrentSpellCast || NeedInterrupt)
                                     && Me.CurrentTarget.Distance <= 4),
                    Cast(SKULL_BASH, ret => gotTarget && SpellManager.HasSpell(SKULL_BASH)
                        && CRSettingsCat.myPrefs.AutoInterrupt
                                    && !spellOnCooldown(SKULL_BASH)
                                    && Me.CurrentTarget.IsCasting
                                    && (Me.CanInterruptCurrentSpellCast || NeedInterrupt)
                                    && Me.CurrentTarget.Distance <= 4),
                Cast(THRASH, ret => gotTarget 
                    && SpellManager.HasSpell(THRASH)
                    && !debuffExists(THRASH, Me.CurrentTarget)
                    && (Me.EnergyPercent >= 50 || buffExists(CLEARCASTING, Me))
                    && Me.CurrentTarget.Distance <= 4),
                Cast(SWIPE, ret => gotTarget && Me.EnergyPercent >= 45 && Me.CurrentTarget.Distance <= 4)
                );
        }
        #endregion

        #region bear rotation
        Composite BearRotation()
        {
            return new PrioritySelector(
                Cast(BEAR_FORM, ret => Me.Shapeshift != ShapeshiftForm.Bear),
                new Decorator(ret => gotTarget && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget), new Action(delegate { Me.CurrentTarget.Face(); return RunStatus.Failure; })),
                CastWildCharge(WILD_CHARGE, ret => AllowMovement && !spellOnCooldown(WILD_CHARGE) && Me.CurrentTarget.InLineOfSight && CanCastWildCharge(8, 25)),
                Cast(FAERIE_FIRE, ret => gotTarget 
                    && SpellManager.HasSpell(FAERIE_FIRE)
                    && !SpellManager.HasSpell(FAERIE_SWARM)
                    && !spellOnCooldown(FAERIE_FIRE)
                    && (!debuffExists(WEAKENED_ARMOR, Me.CurrentTarget) || !debuffExists(FAERIE_FIRE, Me.CurrentTarget))
                    && Me.CurrentTarget.Distance <= 35),
                Cast(FAERIE_SWARM, ret => gotTarget
                    && !SpellManager.HasSpell(FAERIE_SWARM)
                    && !spellOnCooldown(FAERIE_FIRE)
                    && (!debuffExists(WEAKENED_ARMOR, Me.CurrentTarget) || !debuffExists(FAERIE_SWARM, Me.CurrentTarget))
                    && Me.CurrentTarget.Distance <= 35),
                Cast(MIGHTY_BASH, ret => gotTarget && !spellOnCooldown(MIGHTY_BASH)
                      && Me.CurrentTarget.IsCasting
                      && (Me.CanInterruptCurrentSpellCast || NeedInterrupt)
                      && LastSpell != MIGHTY_BASH
                      && LastSpell != SKULL_BASH
                      && Me.CurrentTarget.Distance <= 4),
                Cast(SKULL_BASH, ret => gotTarget && !spellOnCooldown(SKULL_BASH)
                      && Me.CurrentTarget.IsCasting
                      && (Me.CanInterruptCurrentSpellCast || NeedInterrupt)
                      && LastSpell != MIGHTY_BASH
                      && LastSpell != SKULL_BASH
                      && Me.CurrentTarget.Distance <= 4),
                Cast(WAR_STOMP, ret => gotTarget 
                    && Me.Race == WoWRace.Tauren 
                    && !spellOnCooldown(WAR_STOMP) 
                    && Me.CurrentTarget.IsCasting
                    && (Me.CanInterruptCurrentSpellCast || NeedInterrupt)
                    && CRSettingsCat.myPrefs.AutoInterrupt 
                    && LastSpell != MIGHTY_BASH && LastSpell != SKULL_BASH 
                    && Me.CurrentTarget.Distance <= 4),
                
                Cast(FORCE_OF_NATURE, ret => gotTarget 
                    && CRSettingsCat.myPrefs.ForceOfNature 
                    && UseForceOfNaure
                    && Me.CurrentTarget.Distance <= 4),
                Cast(BERSERK, ret => gotTarget && SpellManager.HasSpell(BERSERK)
                                    && isBoss
                                    && !spellOnCooldown(BERSERK)
                                    && Me.CurrentTarget.Distance <= 4),
                Cast(INCARNATION, ret => gotTarget && SpellManager.HasSpell(INCARNATION)
                                    && isBoss
                                    && CRSettingsCat.myPrefs.useIncarnation
                                    && !spellOnCooldown(INCARNATION)
                                    && Me.CurrentTarget.Distance <= 4),
                new Decorator(ret => gotTarget && Me.Combat && CRSettingsCat.myPrefs.useVirmenPotions && isBoss && Me.CurrentTarget.Distance <= 4 && !Me.CurrentTarget.Name.Contains("Dummy"), new Action(ret => { VirmenPotion(); return RunStatus.Failure; })),
                
                Cast(BERSERKING, ret => gotTarget && SpellManager.HasSpell(BERSERKING)
                                    && CRSettingsCat.myPrefs.useBerserking
                                    && !spellOnCooldown(BERSERKING)
                                    && NotHaveHasteBuffs()
                                    && Me.CurrentTarget.Distance <= 4),
                Cast(MAUL, ret => gotTarget && Me.RagePercent >= 60 && Me.CurrentTarget.Distance <= 4),
                Cast(BEAR_THRASH, ret => gotTarget && !spellOnCooldown(BEAR_THRASH) && !debuffExists(BEAR_THRASH, Me.CurrentTarget) && Me.CurrentTarget.Distance <= 4),
                Cast(BEAR_MANGLE, ret => !spellOnCooldown(BEAR_MANGLE) && Me.CurrentTarget.Distance <= 4),
                Cast(LACERATE, ret => gotTarget && !spellOnCooldown(LACERATE)
                       && !debuffExists(LACERATE, Me.CurrentTarget)
                       || (debuffExists(LACERATE, Me.CurrentTarget) && debuffStackCount(LACERATE, Me.CurrentTarget) <= 3)
                       && Me.CurrentTarget.Distance <= 4),
                Cast(LIFEBLOOD, ret => gotTarget 
                    && isBoss 
                    && NotHaveHasteBuffs() 
                    && !spellOnCooldown(LIFEBLOOD)
                    && Me.CurrentTarget.Distance <= 4),
                Cast(BEAR_SWIPE, ret => gotTarget && addCount > 1 && !PauseAoe && Me.RagePercent >= 15 && Me.CurrentTarget.Distance <= 4)
                );
        }
        #endregion
    }
}
